{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 本文件为python3 cookbook的学习记录\n",
    "\n",
    "\n",
    "# chapter01 数据结构和算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4 5\n",
      "50 (2012, 12, 21)\n"
     ]
    }
   ],
   "source": [
    "# 将序列分解为单独的变量\n",
    "'''\n",
    "现在有一个包含 N 个元素的元组或者是序列，怎样将它里面的值解压后同时赋值给 N 个变量？\n",
    "'''\n",
    "p=(4,5)\n",
    "x,y=p\n",
    "print(x,y)\n",
    "\n",
    "data = [ 'ACME', 50, 91.1, (2012, 12, 21) ]\n",
    "\n",
    "_,shares,_,tup=data\n",
    "print(shares,tup)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 [3, 4]\n"
     ]
    }
   ],
   "source": [
    "a,*bc='123' #python2 不支持星号表达式(星号解压语法)\n",
    "\n",
    "def test(*args): #python2和python3都支持\n",
    "    a,b,*c=args\n",
    "    print(a,b,c)\n",
    "\n",
    "test(1,2,3,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "deque([1, [2, 3], 4], maxlen=3)\n",
      "deque([[2, 3], 4, 10], maxlen=3)\n",
      "deque([100, [2, 3], 4], maxlen=3)\n"
     ]
    }
   ],
   "source": [
    "# 保留最后N个元素\n",
    "# 使用collections.deque实现\n",
    "from collections import deque\n",
    "q=deque(maxlen=3)\n",
    "q.append(1)\n",
    "q.append([2,3])\n",
    "q.append(4)\n",
    "print(q)\n",
    "q.append(10)\n",
    "print(q)\n",
    "q.appendleft(100)\n",
    "print(q)\n",
    "#在队列两端插入或删除元素时间复杂度都是 O(1) ，区别于列表，在列表的开头插入或删除元素的时间复杂度为 O(N) 。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[29, 23, 18]\n",
      "[-4, 1, 2]\n",
      "[-4, 7, 1, 23, 8, 2, 18, 29]\n",
      "-4\n",
      "[1, 7, 2, 23, 8, 29, 18]\n",
      "1\n",
      "[2, 7, 18, 23, 8, 29]\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "# 查找最小或最大的N个数\n",
    "#解决方案：heapq 堆\n",
    "\n",
    "'''\n",
    "堆数据结构最重要的特征是 heap[0] 永远是最小的元素\n",
    "'''\n",
    "import heapq\n",
    "\n",
    "nums=[1,8,2,23,7,-4,18,29]\n",
    "print(heapq.nlargest(3,nums))\n",
    "print(heapq.nsmallest(3,nums))\n",
    "h=nums\n",
    "heapq.heapify(h)\n",
    "print(h)\n",
    "print(heapq.heappop(h))\n",
    "print(h)\n",
    "print(heapq.heappop(h))\n",
    "print(h)\n",
    "print(heapq.heappop(h))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'{\"a\": 1, \"b\": 2}'"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 字典保持插入时的顺序\n",
    "import json\n",
    "from collections import OrderedDict #OrderedDict 内部维护着一个根据键插入顺序排序的双向链表\n",
    "d=OrderedDict()\n",
    "d['a']=1\n",
    "d['b']=2\n",
    "d\n",
    "json.dumps(d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[3, 6]\n",
      "slice(2, 4, None)\n",
      "[3, 6]\n"
     ]
    }
   ],
   "source": [
    "items=[0,1,3,6,9]\n",
    "a=slice(2,4)\n",
    "print(items[2:4])\n",
    "print(a)\n",
    "print(items[a])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chapter02 字符串和文本"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "['.DS_Store', 'sources', 'cookbook.ipynb']"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用多个界定字符分割字符串\n",
    "\n",
    "import re\n",
    "line='asdf fjdk; afed, fjek,asdf, foo'\n",
    "a=re.split(r'[;,\\s]\\s*',line)\n",
    "print(a)\n",
    "import os\n",
    "os.listdir('.')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Today is 2012-11-27. PyCon starts 2013-3-13.\n",
      "('11', '27', '2012')\n",
      "1:2:3:5:56\n"
     ]
    }
   ],
   "source": [
    "# 字符串搜索和替换\n",
    "import re\n",
    "text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'\n",
    "print(re.sub(r'(\\d+)/(\\d+)/(\\d+)',r'\\3-\\1-\\2',text))\n",
    "a=re.search(r'(\\d+)/(\\d+)/(\\d+)', text)\n",
    "print(a.groups())\n",
    "re.findall(r'(\\d+)/(\\d+)/(\\d+)', text)\n",
    "\n",
    "print(1,2,3,5,56,sep=\":\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "selfeasy has 100 messages. selfeasy has 100 messages.\n"
     ]
    }
   ],
   "source": [
    "# 字符串格式化\n",
    "\n",
    "a='{name} has {n} messages.'.format(name='selfeasy',n=100)\n",
    "b=\"%s has %s messages.\" %('selfeasy',100)\n",
    "print(a,b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chapter03数字日期和时间"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5.3\n",
      "0b10011010010\n",
      "0o2322\n",
      "0x4d2\n",
      "10011010010\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(4+8j)"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#数字的四舍五入\n",
    "\n",
    "round(1.235,2)\n",
    "\n",
    "from decimal import Decimal\n",
    "a=Decimal('3.12')\n",
    "b=1.2\n",
    "c=4.1\n",
    "print(c+b)\n",
    "\n",
    "x=1234\n",
    "print(bin(x))\n",
    "print(oct(x))\n",
    "print(hex(x))\n",
    "print(format(x,'b'))#不输出进制前缀\n",
    "\n",
    "complex(4,8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2022-04-26 10:13:02.312345\n",
      "2022-02-12 00:00:00\n",
      "73 days, 10:13:02.312345 73\n",
      "2022-04-26 10:13:02\n"
     ]
    }
   ],
   "source": [
    "# 时间与日期转换\n",
    "\n",
    "import datetime\n",
    "import time\n",
    "a=datetime.datetime.now()\n",
    "print(a)\n",
    "a+datetime.timedelta(days=-2)\n",
    "b=datetime.datetime(2022,2,12)\n",
    "print(b)\n",
    "sub=a-b\n",
    "print(sub,sub.days)\n",
    "\n",
    "c=time.time()\n",
    "d=time.localtime(c)\n",
    "print(time.strftime(\"%Y-%m-%d %H:%M:%S\",d))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chapter04迭代器与生成器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "[6, 7, 8, 9]\n"
     ]
    }
   ],
   "source": [
    "# 迭代器切片\n",
    "\n",
    "def count(n):\n",
    "    while n<10:\n",
    "        yield n\n",
    "        n+=1\n",
    "\n",
    "c=count(0)\n",
    "#print(c[0:3]) #生成器对象不能做切片操作\n",
    "import itertools\n",
    "for x in itertools.islice(c,2,6):\n",
    "    print(x)\n",
    "\n",
    "print(list(c)) #islice会消耗掉传入的迭代器数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('a', 'b', 'c')\n",
      "('a', 'c', 'b')\n",
      "('b', 'a', 'c')\n",
      "('b', 'c', 'a')\n",
      "('c', 'a', 'b')\n",
      "('c', 'b', 'a')\n",
      "<zip object at 0x1134f63c0>\n",
      "(1, 'x')\n",
      "(2, 'y')\n",
      "(3, 'z')\n",
      "('x', 1)\n",
      "('y', 2)\n",
      "('z', 3)\n",
      "(None, 4)\n",
      "(None, 5)\n"
     ]
    }
   ],
   "source": [
    "# 排列组合\n",
    "\n",
    "import itertools\n",
    "from itertools import permutations\n",
    "items=['a','b','c']\n",
    "\n",
    "for p in permutations(items):\n",
    "    print(p)\n",
    "\n",
    "a=['x','y','z']\n",
    "b=[1,2,3,4,5]\n",
    "c=zip(b,a)#得到一个可返回元组的迭代器，一旦其中某序列到结尾，则迭代结束\n",
    "print(c)\n",
    "for i in c:\n",
    "    print(i)\n",
    "\n",
    "c=itertools.zip_longest(a,b)\n",
    "for i in c:\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "6\n",
      "7\n",
      "8\n",
      "12\n",
      "9\n",
      "11\n"
     ]
    }
   ],
   "source": [
    "# 将多层嵌套的序列展开为一个单层序列\n",
    "\n",
    "from collections import Iterable\n",
    "\n",
    "def flattern(items,ignore_types=(str,bytes)):\n",
    "    for x in items:\n",
    "        if isinstance(x,Iterable) and not isinstance(x,ignore_types):\n",
    "            yield from flattern(x)\n",
    "        else:\n",
    "            yield x\n",
    "\n",
    "items=[1,2,3,[4,6,7,[8,12]],9,11]\n",
    "for x in flattern(items):\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chapter05文件与IO"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'hello world selfeasy\\n'"
      ]
     },
     "execution_count": 116,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用操作类对象来操作文本或者二进制字符串\n",
    "import io\n",
    "s=io.StringIO()\n",
    "s.write(\"hello world \")\n",
    "print('selfeasy',file=s)\n",
    "s.getvalue()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chapter06数据编码和处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Symbol', 'Price', 'Date', 'Time', 'Change', 'Volume']\n",
      "['AA', '39.48', '6/11/2007', '9:36am', '-0.18', '181800']\n",
      "['AIG', '71.38', '6/11/2007', '9:36am', '-0.15', '195500']\n",
      "['AXP', '62.58', '6/11/2007', '9:36am', '-0.46', '935000']\n",
      "['BA', '98.31', '6/11/2007', '9:36am', '+0.12', '104800']\n",
      "['C', '53.08', '6/11/2007', '9:36am', '-0.25', '360900']\n",
      "['CAT', '78.29', '6/11/2007', '9:36am', '-0.23', '225400']\n",
      "Row(Symbol='AA', Price='39.48', Date='6/11/2007', Time='9:36am', Change='-0.18', Volume='181800')\n",
      "Row(Symbol='AIG', Price='71.38', Date='6/11/2007', Time='9:36am', Change='-0.15', Volume='195500')\n",
      "Row(Symbol='AXP', Price='62.58', Date='6/11/2007', Time='9:36am', Change='-0.46', Volume='935000')\n",
      "Row(Symbol='BA', Price='98.31', Date='6/11/2007', Time='9:36am', Change='+0.12', Volume='104800')\n",
      "Row(Symbol='C', Price='53.08', Date='6/11/2007', Time='9:36am', Change='-0.25', Volume='360900')\n",
      "Row(Symbol='CAT', Price='78.29', Date='6/11/2007', Time='9:36am', Change='-0.23', Volume='225400')\n",
      "OrderedDict([('Symbol', 'AA'), ('Price', '39.48'), ('Date', '6/11/2007'), ('Time', '9:36am'), ('Change', '-0.18'), ('Volume', '181800')])\n",
      "OrderedDict([('Symbol', 'AIG'), ('Price', '71.38'), ('Date', '6/11/2007'), ('Time', '9:36am'), ('Change', '-0.15'), ('Volume', '195500')])\n",
      "OrderedDict([('Symbol', 'AXP'), ('Price', '62.58'), ('Date', '6/11/2007'), ('Time', '9:36am'), ('Change', '-0.46'), ('Volume', '935000')])\n",
      "OrderedDict([('Symbol', 'BA'), ('Price', '98.31'), ('Date', '6/11/2007'), ('Time', '9:36am'), ('Change', '+0.12'), ('Volume', '104800')])\n",
      "OrderedDict([('Symbol', 'C'), ('Price', '53.08'), ('Date', '6/11/2007'), ('Time', '9:36am'), ('Change', '-0.25'), ('Volume', '360900')])\n",
      "OrderedDict([('Symbol', 'CAT'), ('Price', '78.29'), ('Date', '6/11/2007'), ('Time', '9:36am'), ('Change', '-0.23'), ('Volume', '225400')])\n"
     ]
    }
   ],
   "source": [
    "# 读取csv数据\n",
    "\n",
    "import csv\n",
    "from collections import namedtuple\n",
    "\n",
    "with open('./sources/stock.csv') as f:\n",
    "    f_csv=csv.reader(f)\n",
    "    headers=next(f_csv)\n",
    "    print(headers)\n",
    "    for row in f_csv:\n",
    "        print(row)\n",
    "\n",
    "with open('./sources/stock.csv') as f:\n",
    "    f_csv=csv.reader(f)\n",
    "    headers=next(f_csv)\n",
    "    Row=namedtuple('Row',headers) #使用命名元组\n",
    "    for i in f_csv:\n",
    "        row=Row(*i)\n",
    "        print(row)\n",
    "\n",
    "\n",
    "with open('./sources/stock.csv') as f:\n",
    "    f_csv=csv.DictReader(f) #读取到字典序列\n",
    "    for row in f_csv:\n",
    "        print(row)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chapter07函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'x': int, 'y': int, 'return': int}"
      ]
     },
     "execution_count": 118,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 函数注解\n",
    "def add(x:int, y:int)->int:\n",
    "    return x + y\n",
    "\n",
    "print(1+2)\n",
    "add.__annotations__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3 4\n"
     ]
    }
   ],
   "source": [
    "# 减少可调用参数的个数\n",
    "from functools import partial\n",
    "def spam(a,b,c,d):\n",
    "    print(a,b,c,d)\n",
    "\n",
    "#partial()固定某些参数并返回一个新的callable对象。这个新的callable接受未赋值的参数，然后跟之前已经赋值过的参数合并起来，最后将所有参数传递给原始函数。\n",
    "s1=partial(spam,1)#a=1\n",
    "s1(2,3,4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chapter08类与对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3,4)\n",
      "my name is selfeasy, age is 14\n",
      "my name is 'selfeasy', age is 14\n",
      "my name is 'selfeasy', age is 14\n"
     ]
    }
   ],
   "source": [
    "# 改变对象的字符串显示\n",
    "class Pair:\n",
    "    def __init__(self,x,y):\n",
    "        self.x=x\n",
    "        self.y=y\n",
    "\n",
    "    def __repr__(self): #内置的 repr() 函数返回这个字符串，跟我们使用交互式解释器显示的值是一样的\n",
    "        return 'Pair({0.x!r},{0.y!r})'.format(self)\n",
    "\n",
    "    def __str__(self):#__str__() 方法将实例转换为一个字符串，使用 str() 或 print() 函数会输出这个字符串\n",
    "        return '({0.x!r},{0.y!r})'.format(self)\n",
    "p=Pair(3,4)\n",
    "p\n",
    "print(p)\n",
    "\n",
    "#特别来讲，!r 格式化代码指明输出使用 __repr__() 来代替默认的 __str__() \n",
    "'''\n",
    "%s是将变量传到str()函数中，结果是将变量转化适合人阅读的格式\n",
    "%r是将变量穿到repr()函数中，结果是将变量转化成适合机器阅读的格式，可以将%r后的变量理解为一个对象\n",
    "'''\n",
    "print('my name is %s, age is %s'%('selfeasy',14))\n",
    "print('my name is %r, age is %r'%('selfeasy',14))\n",
    "print('my name is {0!r}, age is {1!r}'.format('selfeasy',14))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'26/4/2022'"
      ]
     },
     "execution_count": 129,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 自定义字符串的格式化\n",
    "_formats = {\n",
    "    'ymd' : '{d.year}-{d.month}-{d.day}',\n",
    "    'mdy' : '{d.month}/{d.day}/{d.year}',\n",
    "    'dmy' : '{d.day}/{d.month}/{d.year}'\n",
    "    }\n",
    "\n",
    "class Date:\n",
    "    def __init__(self,year,month,day):\n",
    "        self.year = year\n",
    "        self.month = month\n",
    "        self.day=day\n",
    "\n",
    "    def __format__(self,code):\n",
    "        if code=='':\n",
    "            code='ymd'\n",
    "        fmt=_formats[code]\n",
    "        return fmt.format(d=self)\n",
    "\n",
    "d=Date(2022,4,26)\n",
    "format(d)\n",
    "format(d,'dmy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 让对象支持上下文管理器协议\n",
    "import socket\n",
    "from functools import partial\n",
    "class Lazyconnect(object):\n",
    "    def __init__(self,address, family=socket.AF_INET, type=socket.SOCK_STREAM):\n",
    "        self.address = address\n",
    "        self.family = family\n",
    "        self.type = type\n",
    "        self.socket = None\n",
    "\n",
    "    def __enter__(self):\n",
    "        if self.socket is not None: \n",
    "            raise RuntimeError('already connected')\n",
    "        self.socket = socket.socket(self.family, self.type)\n",
    "        self.socket.connect(self.address)\n",
    "        return self.socket\n",
    "    \n",
    "    def __exit__(self, exc_type, exc_value, trace):\n",
    "        self.socket.close()\n",
    "        self.socket=None\n",
    "\n",
    "'''\n",
    "上下文管理器协议: __enter__、__exit__。可以使用with 语句\n",
    "'''\n",
    "conn = Lazyconnect(('localhost', 80))\n",
    "with conn as s:\n",
    "    s.send(b'GET / HTTP/1.0\\r\\n')\n",
    "    s.send(b'Host: 127.0.0.1\\r\\n')\n",
    "    s.send(b'\\r\\n')\n",
    "    resp = b''.join(iter(partial(s.recv, 1024), b''))\n",
    "    print(resp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# python中的“访问控制”，通过遵循一定的属性和方法命名规约来达到这个效果\n",
    "'''\n",
    "任何以单下划线_开头的名字都应该是内部实现\n",
    "双下划线开始会导致访问名称变成其他形式\n",
    "'''\n",
    "class C():\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.__private = 1 # Does not override B.__private\n",
    "\n",
    "    # Does not override B.__private_method()\n",
    "    def __private_method(self):\n",
    "        pass\n",
    "\n",
    "#这里，私有名称 __private 和 __private_method 被重命名为 _C__private 和 _C__private_method"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "B. spam\n",
      "A. spam\n"
     ]
    }
   ],
   "source": [
    "# 调用父类方法\n",
    "class A:\n",
    "    def spam(self):\n",
    "        print('A. spam')\n",
    "\n",
    "class B(A):\n",
    "    def spam(self):\n",
    "        print('B. spam')\n",
    "        # super().spam()\n",
    "        super(B,self).spam()\n",
    "b=B()\n",
    "b.spam()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Base. __init__\n",
      "B. __init__\n",
      "A. __init__\n",
      "C. __init__\n",
      "A. test\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(__main__.C, __main__.A, __main__.B, __main__.Base, object)"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 多继承 调用顺序  ****\n",
    "'''\n",
    "为了实现继承，Python会在MRO列表上从左到右开始查找基类，直到找到第一个匹配这个属性的类为止。\n",
    "当使用super函数时，python会在MRO列表上继续搜索下一个类\n",
    "'''\n",
    "class Base(object):\n",
    "    def __init__(self):\n",
    "        print('Base. __init__')\n",
    "\n",
    "class A(Base):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        print('A. __init__')\n",
    "\n",
    "    def test(self):\n",
    "        print('A. test')\n",
    "\n",
    "class B(Base):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        print('B. __init__')\n",
    "\n",
    "    def test(self):\n",
    "        print('B. test')\n",
    "\n",
    "class C(A,B):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        print('C. __init__')\n",
    "\n",
    "c=C()\n",
    "c.test()\n",
    "C.__mro__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "self is <__main__.D object at 0x10756a810> @D.add\n",
      "self is <__main__.D object at 0x10756a810> @B.add\n",
      "self is <__main__.D object at 0x10756a810> @C.add\n",
      "self is <__main__.D object at 0x10756a810> @A.add\n",
      "19\n",
      "[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]\n"
     ]
    }
   ],
   "source": [
    "class A:\n",
    "    def __init__(self):\n",
    "        self.n = 2\n",
    "\n",
    "    def add(self, m):\n",
    "        # 第四步\n",
    "        # 来自 D.add 中的super\n",
    "        # self==d, self.n==d, n==5\n",
    "        print('self is {0} @A.add'.format(self))\n",
    "        self.n += m\n",
    "        # d.n==7\n",
    "\n",
    "class B(A):\n",
    "    def __init__(self):\n",
    "        self.n = 3\n",
    "\n",
    "    def add(self, m):\n",
    "        # 第二步\n",
    "        # 来自 D.add 中的 super\n",
    "        # self==d, self.n==d, n==5\n",
    "        print('self is {0} @B.add'.format(self))\n",
    "        # 等价于 super(B, self).add(m)\n",
    "        # self 的 MRO 是[D, B, C, A, object]\n",
    "        # 从 B 之后的[C, A, object]中查找 add 方法\n",
    "        super().add(m)\n",
    "        \n",
    "        # 第六步\n",
    "        # d.n=11\n",
    "        self.n += 3\n",
    "        # d.n=14\n",
    "\n",
    "class C(A):\n",
    "    def __init__(self):\n",
    "        self.n = 4\n",
    "\n",
    "    def add(self, m):\n",
    "        # 第三步\n",
    "        # 来自 B.add 中的 super\n",
    "        # self==d, self.n==d, n==5\n",
    "        print('self is {0} @C.add'.format(self))\n",
    "        # 等价于 super(C, self).add(m)\n",
    "        # self 的 MRO 是[D, B, C, A, object]\n",
    "        # 从 C 之后的[A, object] 中查找 add 方法\n",
    "        \n",
    "        super().add(m)\n",
    "        # 第五步\n",
    "        # d.n=7\n",
    "        self.n += 4\n",
    "        # d.n=11\n",
    "\n",
    "class D(B, C):\n",
    "    def __init__(self):\n",
    "        self.n = 5\n",
    "\n",
    "    def add(self, m):\n",
    "        # 第一步\n",
    "        print('self is {0} @D.add'.format(self))\n",
    "        # 等价 super(D, self).add(m)\n",
    "        # self 的 MRO 是[D, B, C, A, object]\n",
    "        # 从 D 之后的[B, C, A, object]中查找 add 方法\n",
    "        super().add(m)\n",
    "        # 第七步\n",
    "        # d.n=14\n",
    "        self.n += 5\n",
    "        # self.n=19\n",
    "\n",
    "d = D()\n",
    "d.add(2)\n",
    "print(d.n)\n",
    "print(D.mro())\n",
    "# https://www.cnblogs.com/keye/p/15671711.html super() 多继承"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "compute area\n",
      "380.132711084365\n",
      "380.132711084365\n"
     ]
    }
   ],
   "source": [
    "# 延迟计算属性\n",
    "class lazyproperty:\n",
    "    def __init__(self,func):\n",
    "        self.func=func\n",
    "\n",
    "    def __get__(self,instance, cls):\n",
    "        if instance is None:\n",
    "            return self\n",
    "        else:\n",
    "            value = self.func(instance)\n",
    "            setattr(instance,self.func.__name__,value)\n",
    "            return value\n",
    "\n",
    "\n",
    "import math\n",
    "\n",
    "class Circle(object):\n",
    "    def __init__(self,radius):\n",
    "        self.radius=radius\n",
    "\n",
    "    @lazyproperty\n",
    "    def area(self):\n",
    "        print('compute area')\n",
    "        return math.pi * self.radius**2\n",
    "\n",
    "C=Circle(11)\n",
    "print(C.area)\n",
    "print(C.area)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'xs', '12': 10, '14': 11}"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 简化数据结构的初始化\n",
    "class Structure1:\n",
    "    # Class variable that specifies expected fields\n",
    "    _fields = []\n",
    "\n",
    "    def __init__(self, *args):\n",
    "        if len(args) != len(self._fields):\n",
    "            raise TypeError('Expected {} arguments'.format(len(self._fields)))\n",
    "        # Set the arguments\n",
    "        for name, value in zip(self._fields, args):\n",
    "            setattr(self, name, value)\n",
    "\n",
    "class sub(Structure1):\n",
    "    _fields=['name','12','14']\n",
    "\n",
    "test=sub('xs',10,11)\n",
    "vars(test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义接口或者抽象类\n",
    "#抽象类的目的就是让别的类继承它并实现特定的抽象方法\n",
    "from abc import ABCMeta, abstractmethod\n",
    "\n",
    "class Item(metaclass=ABCMeta):\n",
    "    @abstractmethod\n",
    "    def read(self):\n",
    "        pass\n",
    "a=Item() # 抽象类不能被实例化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Setting x = 23\n",
      "Getting x\n",
      "23\n",
      "Deleting x\n"
     ]
    }
   ],
   "source": [
    "# 利用混入类Mixins扩展类功能\n",
    "'''\n",
    "对于混入类，有几点需要记住。首先是，混入类不能直接被实例化使用。 \n",
    "其次，混入类没有自己的状态信息，也就是说它们并没有定义 __init__() 方法，并且没有实例属性。 这也是为什么我们在上面明确定义了 __slots__ = () 。\n",
    "'''\n",
    "class LoggedMappingMixin:\n",
    "    \"\"\"\n",
    "    Add logging to get/set/delete operations for debugging.\n",
    "    \"\"\"\n",
    "    __slots__ = ()  # 混入类都没有实例变量，因为直接实例化混入类没有任何意义\n",
    "\n",
    "    def __getitem__(self, key):\n",
    "        print('Getting ' + str(key))\n",
    "        return super().__getitem__(key)\n",
    "\n",
    "    def __setitem__(self, key, value):\n",
    "        print('Setting {} = {!r}'.format(key, value))\n",
    "        return super().__setitem__(key, value)\n",
    "\n",
    "    def __delitem__(self, key):\n",
    "        print('Deleting ' + str(key))\n",
    "        return super().__delitem__(key)\n",
    "\n",
    "\n",
    "class SetOnceMappingMixin:\n",
    "    '''\n",
    "    Only allow a key to be set once.\n",
    "    '''\n",
    "    __slots__ = ()\n",
    "\n",
    "    def __setitem__(self, key, value):\n",
    "        if key in self:\n",
    "            raise KeyError(str(key) + ' already set')\n",
    "        return super().__setitem__(key, value)\n",
    "\n",
    "\n",
    "class StringKeysMappingMixin:\n",
    "    '''\n",
    "    Restrict keys to strings only\n",
    "    '''\n",
    "    __slots__ = ()\n",
    "\n",
    "    def __setitem__(self, key, value):\n",
    "        if not isinstance(key, str):\n",
    "            raise TypeError('keys must be strings')\n",
    "        return super().__setitem__(key, value)\n",
    "\n",
    "class LoggedDict(LoggedMappingMixin, dict):\n",
    "    pass\n",
    "\n",
    "d = LoggedDict()\n",
    "d['x'] = 23\n",
    "print(d['x'])\n",
    "del d['x']\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chapter09元编程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "countdown 0.01742386817932129\n"
     ]
    }
   ],
   "source": [
    "# 创建装饰器时保留函数元信息\n",
    "import time\n",
    "from functools import wraps\n",
    "def timethis(func):\n",
    "    '''\n",
    "    Decorator that reports the execution time.\n",
    "    '''\n",
    "    @wraps(func) #保留原函数的元信息\n",
    "    def wrapper(*args, **kwargs):\n",
    "        start = time.time()\n",
    "        result = func(*args, **kwargs)\n",
    "        end = time.time()\n",
    "        print(func.__name__, end-start)\n",
    "        return result\n",
    "    return wrapper\n",
    "\n",
    "@timethis\n",
    "def countdown(n):\n",
    "    '''\n",
    "    Counts down\n",
    "    '''\n",
    "    while n > 0:\n",
    "        n -= 1\n",
    "countdown(100000)\n",
    "countdown.__name__\n",
    "countdown.__annotations__\n",
    "countdown.__wrapped__(50) #wraps 有一个重要特征是它能让你通过属性 __wrapped__ 直接访问被包装函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "spam\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4\n",
      "Spam!\n"
     ]
    }
   ],
   "source": [
    "# 带可选参数的装饰器\n",
    "from functools import wraps, partial\n",
    "import logging\n",
    "\n",
    "def logged(func=None, *, level=logging.DEBUG, name=None, message=None):\n",
    "    if func is None:\n",
    "        return partial(logged, level=level, name=name, message=message)\n",
    "\n",
    "    logname = name if name else func.__module__\n",
    "    log = logging.getLogger(logname)\n",
    "    logmsg = message if message else func.__name__\n",
    "\n",
    "    @wraps(func)\n",
    "    def wrapper(*args, **kwargs):\n",
    "        log.log(level, logmsg)\n",
    "        return func(*args, **kwargs)\n",
    "\n",
    "    return wrapper\n",
    "\n",
    "# Example use\n",
    "@logged\n",
    "def add(x, y):\n",
    "    return x + y\n",
    "\n",
    "@logged(level=logging.CRITICAL, name='example')\n",
    "def spam():\n",
    "    print('Spam!')\n",
    "\n",
    "print(add(1,3))\n",
    "spam()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2 3 4\n"
     ]
    }
   ],
   "source": [
    "# 星号分隔符\n",
    "\n",
    "def test(a,b,*,x,y):\n",
    "    print(a,b,x,y)\n",
    "\n",
    "#test(1,2,3,4) #test() takes 2 positional arguments but 4 were given\n",
    "test(1,2,x=3,y=4) #参数列表里的 * 星号，标志着位置参数的就此终结，之后的那些参数，都只能以关键字形式来指定。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OrderedDict([('x', <class 'int'>), ('y', <class 'int'>)])\n",
      "OrderedDict([('x', 1), ('y', 2)])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 利用装饰器加上类型检查\n",
    "from inspect import signature\n",
    "from functools import wraps\n",
    "import json\n",
    "def typeassert(*ty_args, **ty_kwargs):\n",
    "    def decorate(func):\n",
    "        # If in optimized mode, disable type checking\n",
    "        if not __debug__:\n",
    "            return func\n",
    "\n",
    "        # Map function argument names to supplied types\n",
    "        sig = signature(func)\n",
    "        bound_types = sig.bind_partial(*ty_args, **ty_kwargs).arguments\n",
    "        print(bound_types)\n",
    "\n",
    "        @wraps(func)\n",
    "        def wrapper(*args, **kwargs):\n",
    "            bound_values = sig.bind(*args, **kwargs)\n",
    "            print(bound_values.arguments)\n",
    "            # Enforce type assertions across supplied arguments\n",
    "            for name, value in bound_values.arguments.items():\n",
    "                if name in bound_types:\n",
    "                    if not isinstance(value, bound_types[name]):\n",
    "                        raise TypeError(\n",
    "                            'Argument {} must be {}'.format(name, bound_types[name])\n",
    "                            )\n",
    "            return func(*args, **kwargs)\n",
    "        return wrapper\n",
    "    return decorate\n",
    "\n",
    "@typeassert(int, int)\n",
    "def add(x, y):\n",
    "    return x + y\n",
    "\n",
    "add(1,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "<__main__.Spam object at 0x1099336d0> 1\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "# 将装饰器定义为类\n",
    "import types\n",
    "from functools import wraps\n",
    "\n",
    "class Profiled:\n",
    "    def __init__(self, func):\n",
    "        wraps(func)(self)\n",
    "        self.ncalls = 0\n",
    "\n",
    "    def __call__(self, *args, **kwargs):\n",
    "        self.ncalls += 1\n",
    "        return self.__wrapped__(*args, **kwargs)\n",
    "\n",
    "    def __get__(self, instance, cls):\n",
    "        if instance is None:\n",
    "            return self\n",
    "        else:\n",
    "            return types.MethodType(self, instance) #手动创建一个绑定方法来使用。只有当实例被使用的时候绑定方法才会被创建。\n",
    "\n",
    "@Profiled\n",
    "def add(x, y):\n",
    "    return x + y\n",
    "\n",
    "class Spam:\n",
    "    @Profiled\n",
    "    def bar(self, x):\n",
    "        print(self, x)\n",
    "    \n",
    "print(add(2, 3))\n",
    "print(Spam().bar(1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<__main__.Spam object at 0x1072b8210> 111\n",
      "0.0003361701965332031\n"
     ]
    }
   ],
   "source": [
    "# 为类和静态方法提供装饰器\n",
    "import time\n",
    "from functools import wraps\n",
    "\n",
    "# A simple decorator\n",
    "def timethis(func):\n",
    "    @wraps(func)\n",
    "    def wrapper(*args, **kwargs):\n",
    "        start = time.time()\n",
    "        r = func(*args, **kwargs)\n",
    "        end = time.time()\n",
    "        print(end-start)\n",
    "        return r\n",
    "    return wrapper\n",
    "\n",
    "# Class illustrating application of the decorator to different kinds of methods\n",
    "class Spam:\n",
    "    @timethis\n",
    "    def instance_method(self, n):\n",
    "        print(self, n)\n",
    "        while n > 0:\n",
    "            n -= 1\n",
    "\n",
    "    @classmethod #@classmethod 和 @staticmethod 实际上并不会创建可直接调用的对象， 而是创建特殊的描述器对象,此当你试着在其他装饰器中将它们当做函数来使用时就会出错\n",
    "    @timethis\n",
    "    def class_method(cls, n):\n",
    "        print(cls, n)\n",
    "        while n > 0:\n",
    "            n -= 1\n",
    "\n",
    "    @staticmethod\n",
    "    @timethis\n",
    "    def static_method(n):\n",
    "        print(n)\n",
    "        while n > 0:\n",
    "            n -= 1\n",
    "s=Spam()\n",
    "s.instance_method(111)\n",
    "\n",
    "'''\n",
    "class Spam11:\n",
    "    @timethis #装饰器顺序不能写反，会报错 \n",
    "    @staticmethod\n",
    "    def static_method(n):\n",
    "        print(n)\n",
    "        while n > 0:\n",
    "            n -= 1\n",
    "\n",
    "Spam11.instance_method(111)\n",
    "'''\n",
    "'''\n",
    "顺序不能改变。否则会报错\n",
    "'''\n",
    "from abc import ABCMeta, abstractmethod\n",
    "class A(metaclass=ABCMeta):\n",
    "    @classmethod #顺序不能改变\n",
    "    @abstractmethod\n",
    "    def method(cls):\n",
    "        pass\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ok\n"
     ]
    },
    {
     "ename": "TypeError",
     "evalue": "Can't instantiate directly",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m/var/folders/dl/2qgck9s13mz1b2d3f2h6142w0000gn/T/ipykernel_19775/1916890351.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     12\u001b[0m \u001b[0mSpam\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgrok\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m11\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m \u001b[0mSpam\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/var/folders/dl/2qgck9s13mz1b2d3f2h6142w0000gn/T/ipykernel_19775/1916890351.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0;32mclass\u001b[0m \u001b[0mNoInstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0m__call__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m         \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Can't instantiate directly\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      7\u001b[0m \u001b[0;32mclass\u001b[0m \u001b[0mSpam\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmetaclass\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mNoInstance\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: Can't instantiate directly"
     ]
    }
   ],
   "source": [
    "# 使用元类控制实例的创建\n",
    "\n",
    "class NoInstance(type):\n",
    "    def __call__(self, *args, **kwargs):\n",
    "        raise TypeError(\"Can't instantiate directly\")\n",
    "\n",
    "class Spam(metaclass=NoInstance):\n",
    "    @staticmethod\n",
    "    def grok(x):\n",
    "        print('ok')\n",
    "\n",
    "Spam.grok(11)\n",
    "Spam()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Creating Spam\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "# 实现单例模式\n",
    "\n",
    "class singleton(type):\n",
    "    def __init__(self, *args, **kwargs):\n",
    "        self.__instance=None\n",
    "        super().__init__(*args, **kwargs)\n",
    "    \n",
    "    def __call__(self,*args, **kwargs):\n",
    "        if self.__instance is None:\n",
    "            self.__instance=super().__call__(*args, **kwargs)\n",
    "            return self.__instance\n",
    "        else:\n",
    "            return self.__instance\n",
    "\n",
    "\n",
    "class Spam(metaclass=singleton):\n",
    "    def __init__(self):\n",
    "        print('Creating Spam')\n",
    "\n",
    "a=Spam()\n",
    "b=Spam()\n",
    "print(a is b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chapter10模块与包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 将文件夹加入到sys.path\n",
    "'''\n",
    "创建一个后缀为.pth的文件，将目录列举出来如\n",
    "# myapplication.pth\n",
    "/some/dir\n",
    "/other/dir\n",
    "'''\n",
    "#这个.pth文件需要放在某个Python的site-packages目录。当解释器启动时，.pth文件里列举出来的存在于文件系统的目录将被添加到sys.path。\n",
    "# 安装一个.pth文件可能需要管理员权限，如果它被添加到系统级的Python解释器。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chapter11网络与web编程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建TCP服务器\n",
    "\n",
    "from socketserver import BaseRequestHandler,TCPServer\n",
    "class EchoHandler(BaseRequestHandler):\n",
    "    def handler(self):\n",
    "        print(\"get connection from \", self.client_address)\n",
    "        while True:\n",
    "            msg=self.request.recv(8192)\n",
    "            if not msg:\n",
    "                break\n",
    "            self.request.send(msg)\n",
    "\n",
    "if __name__=='__main__':\n",
    "    serv=TCPServer(('',2000),EchoHandler)\n",
    "    serv.serve_forever()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# chapter12并发编程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#线程\n",
    "import time\n",
    "\n",
    "def countdown(n):\n",
    "    while n>0:\n",
    "        print('T-minus',n)\n",
    "        n-=1\n",
    "        time.sleep(2)\n",
    "\n",
    "from threading import Thread\n",
    "t=Thread(target=countdown,args=(10,))\n",
    "t.start() #执行线程对象\n",
    "t.join() #阻塞线程，直到执行完成"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 对线程进行控制\n",
    "class CountdownTask:\n",
    "    def __init__(self):\n",
    "        self._running = True\n",
    "\n",
    "    def terminate(self):\n",
    "        self._running = False\n",
    "\n",
    "    def run(self, n):\n",
    "        while self._running and n > 0:\n",
    "            print('T-minus', n)\n",
    "            n -= 1\n",
    "            time.sleep(5)\n",
    "\n",
    "c = CountdownTask()\n",
    "t = Thread(target=c.run, args=(10,))\n",
    "t.start()\n",
    "c.terminate() # Signal termination\n",
    "t.join()      # Wait for actual termination (if needed)\n",
    "\n",
    "'''\n",
    "由于全局解释锁（GIL）的原因，Python 的线程被限制到同一时刻只允许一个线程执行这样一个执行模型。\n",
    "所以，Python 的线程更适用于处理I/O和其他需要并发执行的阻塞操作（比如等待I/O、等待从数据库获取数据等等），而不是需要多处理器并行的计算密集型任务。\n",
    "'''"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49"
  },
  "kernelspec": {
   "display_name": "Python 3.7.4 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
